/**
 * 
 */
package com.duowan.cms.service.template;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.ibatis.type.Alias;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.duowan.cms.common.domain.Page;
import com.duowan.cms.common.exception.BaseCheckedException;
import com.duowan.cms.common.service.DoToDtoConvertorFactory;
import com.duowan.cms.common.util.DateUtil;
import com.duowan.cms.common.util.IdManager;
import com.duowan.cms.common.util.LogUtil;
import com.duowan.cms.common.util.PathUtil;
import com.duowan.cms.common.util.StringUtil;
import com.duowan.cms.common.util.ThreadUtil;
import com.duowan.cms.common.webapp.property.ExtendedPropertyPlaceholderConfigurer.PropertiesHolder;
import com.duowan.cms.core.rmi.client.template.TemplateRemoteService;
import com.duowan.cms.domain.article.rpst.ArticleRepository;
import com.duowan.cms.domain.channel.Channel;
import com.duowan.cms.domain.template.Template;
import com.duowan.cms.domain.template.rpst.TemplateRepository;
import com.duowan.cms.dto.article.ArticleSearchCriteria;
import com.duowan.cms.dto.channel.ChannelInfo;
import com.duowan.cms.dto.template.AutoFlushTemplateInfo;
import com.duowan.cms.dto.template.SimpleTemplateInfo;
import com.duowan.cms.dto.template.TemplateCategory;
import com.duowan.cms.dto.template.TemplateInfo;
import com.duowan.cms.dto.template.TemplateSearchCriteria;
import com.duowan.cms.dto.template.TemplateStatus;
import com.duowan.cms.dto.user.UserInfo;
import com.duowan.cms.parser.rmi.client.template.TemplateParserRemoteService;
import com.duowan.cms.service.channel.ChannelService;
import com.duowan.cms.service.user.UserService;

/**
 * @author coolcooldee
 * 
 */
@Service("templateService")
@Alias("templateRemoteService")
public class TemplateServiceImpl implements TemplateService, TemplateRemoteService {

    @Autowired
    private UserService userService;
	
    @Autowired
    private TemplateRepository templateRepository;

    @Autowired
    private ChannelService channelService;

    @Autowired
    private TemplateParserRemoteService templateParserRemoteService;

    @Autowired
    private ArticleRepository articleRepository;
    
    @Autowired
    private AutoFlushTemplateService autoFlushTemplateService;

    private static Logger logger = Logger.getLogger(TemplateService.class);

    public void publish(TemplateInfo templateInfo) throws BaseCheckedException {
        // TODO 如果是“投票结果(新版)”类型模板，做特殊处理，参考旧版
        
    	Template template = this.saveOrUpdateTemplate(templateInfo);
        // 模板解析并且生成静态页面 , 异步处理
        final TemplateInfo finalTemplateInfo = (TemplateInfo) DoToDtoConvertorFactory.getConvertor(Template.class).do2Dto(template);
        this.asynParseTemplateAndGenerateFile(finalTemplateInfo);
    }
    
    
    @Override
	public String publishAndPreview(TemplateInfo templateInfo) throws BaseCheckedException {
    	Template template = this.saveOrUpdateTemplate(templateInfo);
        // 模板解析并且生成静态页面 , 异步处理
        TemplateInfo finalTemplateInfo = (TemplateInfo) DoToDtoConvertorFactory.getConvertor(Template.class).do2Dto(template);
        logger.info("模板["+finalTemplateInfo.getName()+"("+finalTemplateInfo.getId()+")]采用{同步}方式解析模板并且生成静态页面");
        return this.parseTemplateAndGenerateFile(finalTemplateInfo);
    	
	}
    /**
     *  保存或者更新模板
     */
	private Template saveOrUpdateTemplate(TemplateInfo templateInfo) throws BaseCheckedException{
        Template template = null;
        if (templateInfo.getId() == null) {
            template = new Template(templateInfo);
            templateRepository.save(template);
            logger.info("成功创建新模板[channelId=" + templateInfo.getChannelId() + ", templateId=" + templateInfo.getId() + ", templateName = " + template.getName() + "]。");
        }else{
            template = templateRepository.getByChannelIdAndTemplateId(templateInfo.getChannelId(), templateInfo.getId()) ;
            if(template!=null){
                template.update(templateInfo);
                templateRepository.update(template);
                logger.info("成功更新模板[channelId=" + templateInfo.getChannelId() + ", templateId=" + templateInfo.getId() + ", templateName =  " + template.getName() + "]。");
            }else{
                logger.error("该模板[templateid="+templateInfo.getId()+"]在该专区[channelId="+templateInfo.getChannelId()+"]下不存在");
                throw new BaseCheckedException(TemplateService.TEMPLATE_IS_NOT_EXIST_IN_CHANNEL, "该模板在该专区下不存在");
            }
        }
        return template;
    }

    @Override
    public void delete(String channelId, Long templateId) {
        Template template = templateRepository.getByChannelIdAndTemplateId(channelId, templateId);
        templateRepository.delete(template);
        logger.info("成功删除模板[channelId=" + channelId + ", templateId=" + templateId + ", templateName=" + template.getName() + "]");
    }

    @Override
    public Page<TemplateInfo> pageSearch(TemplateSearchCriteria searchCriteria) {
        return templateRepository.pageSearch(searchCriteria);
    }
    
    @Override
    public Page<SimpleTemplateInfo> pageSearch4Show(TemplateSearchCriteria searchCriteria) {
        return templateRepository.pageSearch4Show(searchCriteria);
    }

    @Override
    public String getAllCategoryJson() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public boolean hasArticleUse(String channelId, Long templateId) {
        ArticleSearchCriteria searchCriteria = new ArticleSearchCriteria();
        searchCriteria.setChannelId(channelId);
        searchCriteria.setTemplateId(templateId);
        if (articleRepository.pageSearch(searchCriteria).getData().size() > 0) {
            return true;
        }
        return false;
    }

    /**
     * 保存在session的字符串(templatecopy)形式如下:
     * 原频道id + ","+原频道名+";" + "模板id"+","+"模板名"+";"
     */
    @Override
    public void paste(String channelId, String templatecopy, TemplateInfo templateInfo) {
        String[] tcuts = templatecopy.split(";");
        String channelStr = tcuts[0];
        if (tcuts != null && tcuts.length > 0 && channelStr.indexOf(",") != -1) {
            String oldChannelId = channelStr.substring(0, channelStr.indexOf(","));// 旧频道id
            long templateId = Long.parseLong(tcuts[1].substring(0, tcuts[1].indexOf(",")));
            Template template = templateRepository.getByChannelIdAndTemplateId(oldChannelId, templateId);
            template.setId(IdManager.generateId());
            template.setUserIp(templateInfo.getUserIp());
            template.setProxyIp(templateInfo.getProxyIp());
            template.setLastUpdateUserId(templateInfo.getLastUpdateUserId());
            template.setCreateUserId(templateInfo.getCreateUserId());
            template.setPostTime(new Date());
            template.setUpdateTime(new Date());
            template.setLogs(templateInfo.getLogs());
            template.setChannel(new Channel(channelService.getById(channelId)));
            templateRepository.save(template);
            //进行异步刷模板
            final TemplateInfo finalTemplateInfo = (TemplateInfo) DoToDtoConvertorFactory.getConvertor(Template.class).do2Dto(template);
            this.asynParseTemplateAndGenerateFile(finalTemplateInfo);
        }
    }

    /**
    	* 粘贴后的模板信息与原模板的信息有以下相同:
    	*   1.	Name(模板名) 2.code(编码)  3.templateCategory(模板分类)
    	*   4.digest(说明)  5.alias(别名)

     */
    @Override
    public String pasteAll(String srcChannelId, TemplateInfo newTemplateInfo) throws BaseCheckedException {
        TemplateSearchCriteria srcSearchCriteria = new TemplateSearchCriteria();
        srcSearchCriteria.setChannelId(srcChannelId);
        List<TemplateInfo> srcTemplateInfoList = this.listSearch(srcSearchCriteria);
        StringBuffer sameNameTemplateBuffer = new StringBuffer("失败原因，本频道已存在同名模板。\n同名模板列表如下：");
       
        int successInsertCounter = 0;
        int failInsertCounter = 0;
        for (TemplateInfo srcTemplateInfo : srcTemplateInfoList) {
            Template template = templateRepository.getByChannelIdAndTemplateName(newTemplateInfo.getChannelId(), srcTemplateInfo.getName());
            if (template != null) {
                sameNameTemplateBuffer.append(srcTemplateInfo.getName() + ",");
                failInsertCounter++;
            } else {
               Template newTemplate = new Template(newTemplateInfo);
                newTemplate.setName(srcTemplateInfo.getName());// 模板名
                newTemplate.setCode(srcTemplateInfo.getCode());// 编码
                newTemplate.setTemplateCategory(srcTemplateInfo.getTemplateCategory().getValue());// 分类
                newTemplate.setDigest(srcTemplateInfo.getDigest());// 说明
                newTemplate.setAlias(srcTemplateInfo.getAlias());// 别名
                newTemplate.setContent(srcTemplateInfo.getContent());
                templateRepository.save(newTemplate);
                
                //进行异步刷模板
                final TemplateInfo finalTemplateInfo = (TemplateInfo) DoToDtoConvertorFactory.getConvertor(Template.class).do2Dto(newTemplate);
                this.asynParseTemplateAndGenerateFile(finalTemplateInfo);
                successInsertCounter++;
            }
        }
        ChannelInfo srcChannelInfo = channelService.getById(srcChannelId);
        ChannelInfo destChannelInfo = channelService.getById(newTemplateInfo.getChannelId());
        String resultStr = "从频道[" + srcChannelInfo.getName() + "]全复制到频道[" + destChannelInfo.getName() + "]\n模板总数" + srcTemplateInfoList.size() + "个。成功" + successInsertCounter
                + "个,失败" + failInsertCounter + "个\n" ;
        if (failInsertCounter > 0) {
        	resultStr += sameNameTemplateBuffer.toString();
		}
        return resultStr;
    }

    @Override
    public List<TemplateInfo> listSearch(TemplateSearchCriteria searchCriteria) {
        searchCriteria.setPageSize(null);
        return templateRepository.listSearch(searchCriteria);
    }

    @SuppressWarnings("unchecked")
    @Override
    public TemplateInfo getByChannelIdAndTemplateName(String channelId, String templateName) {
        Template template = templateRepository.getByChannelIdAndTemplateName(channelId, templateName);
        if (template != null)
            return (TemplateInfo) DoToDtoConvertorFactory.getConvertor(Template.class).do2Dto(template);
        return null;
    }

    @Override
    public boolean isTemplateCategoryExist(String channelId, String templateCategory) {
        TemplateSearchCriteria searchCriteria = new TemplateSearchCriteria();
        searchCriteria.setChannelId(channelId);
        searchCriteria.setTemplateCategory(TemplateCategory.getInstance(templateCategory));
        if (templateRepository.pageSearch(searchCriteria).getData().size() > 0) {
            return false;
        }
        return true;
    }

    @SuppressWarnings("unchecked")
    @Override
    public TemplateInfo getByChannelIdAndTemplateId(String channelId, Long templateId) {
        Template template = templateRepository.getByChannelIdAndTemplateId(channelId, templateId);
        if (template != null)
            return (TemplateInfo) DoToDtoConvertorFactory.getConvertor(Template.class).do2Dto(template);
        return null;
    }

    @Override
    public List<TemplateInfo> getByChannelIdAndCategoryOrderByCooperater(String channelId, TemplateCategory category) {
        return templateRepository.getByChannelIdAndCategoryOrderByCooperater(channelId, category);
    }
    
    @Override
    public void markParserFail(String channelId, Long templateId){
        Template template = templateRepository.getByChannelIdAndTemplateId(channelId, templateId);
        template.setTemplateStatus(TemplateStatus.PASER_ERROR);
        templateRepository.update(template);
    }
    
    @Override
    public void markParserFail(String channelId, Long templateId, String reason){
        Template template = templateRepository.getByChannelIdAndTemplateId(channelId, templateId);
        template.setTemplateStatus(TemplateStatus.PASER_ERROR);
        template.setLogs(LogUtil.getLogBeforeTen(StringUtil.escapeHTMLTags(reason)+"<br>\n" +template.getLogs()));
        templateRepository.update(template);
    }
    
    @Override
    public void markParserSuccess(String channelId, Long templateId){
        Template template = templateRepository.getByChannelIdAndTemplateId(channelId, templateId);
        template.setTemplateStatus(TemplateStatus.NORMAL);
        templateRepository.update(template);
    }
    
    private String parseTemplateAndGenerateFile(TemplateInfo finalTemplateInfo){
    	 try {
             templateParserRemoteService.parseTemplateAndGenerateFile(channelService.getById(finalTemplateInfo.getChannelId()), finalTemplateInfo);
             logger.info("成功解析模板[channelId=" + finalTemplateInfo.getChannelId() + ", templateId=" + finalTemplateInfo.getId() + ", templateName = "
                     + finalTemplateInfo.getName() + "]。");
         } catch (Exception e) {
             logger.error("出现异常，解析模板[channelId=" + finalTemplateInfo.getChannelId() + ", templateId=" + finalTemplateInfo.getId() + ", templateName = "
                     + finalTemplateInfo.getName() + "]出错，异常原因：" + e);
         }
    	String channelId = finalTemplateInfo.getChannelId();
    	 return PathUtil.getTemplateOnCmsUrl(channelService.getById(channelId).getId(), finalTemplateInfo.getId(), finalTemplateInfo.getAlias());
    }
    
    //异步的解析模板并且生成静态页面
    private void asynParseTemplateAndGenerateFile(final TemplateInfo finalTemplateInfo ){
        ThreadUtil.getThreadPool().execute(new Runnable() {
            @Override
            public void run() {
            	logger.info("模板["+finalTemplateInfo.getName()+"("+finalTemplateInfo.getId()+")]采用{异步}方式解析模板并且生成静态页面");
            	parseTemplateAndGenerateFile(finalTemplateInfo);
            }
        });
    }


    @Override
    public List<TemplateInfo> listAutoFlushTemplates() {
        List<TemplateInfo> list = new ArrayList<TemplateInfo>();
        List<AutoFlushTemplateInfo> flushTemplateInfos = autoFlushTemplateService.getAllAutoFlushTemplate();
        for(AutoFlushTemplateInfo autoFlushTemplateInfo : flushTemplateInfos){
             Date date = autoFlushTemplateInfo.getLastFlushTime();  //最后刷新时间
             int interval = autoFlushTemplateInfo.getInterval();    //间隔时间
             if(date==null){
                 list.add(this.getByChannelIdAndTemplateId(autoFlushTemplateInfo.getChannelInfo().getId(), autoFlushTemplateInfo.getTemplateId()));
             }else{
                 Date date2 = new Date(date.getTime()+interval*1000);
                 if(DateUtil.compareDateTimeIgnoreMillisecond(new Date(), date2)>0){
                     list.add(this.getByChannelIdAndTemplateId(autoFlushTemplateInfo.getChannelInfo().getId(), autoFlushTemplateInfo.getTemplateId()));
                 }
             }
        }
        return list;
    }

    /**
     * 判断是否拥有复制最终页模板的权限
     * 		1.首先判断是否是该模板是否是最终文章页模板
     * 		2.判断用户是否有权限.
     */
    @Override
	public boolean hasPermissionCopyFinalTemplate(String channelId , UserInfo userInfo , Long templateId ) {
    	TemplateInfo templateInfo = this.getByChannelIdAndTemplateId(channelId, templateId);
    	if (templateInfo.getTemplateCategory() == TemplateCategory.FINAL_ARTICLE) {
        	String powerId = PropertiesHolder.get("copyFinalTemplate");//复制/粘贴最终文章页模板的权限
        	return userService.hasPower( channelId, userInfo ,powerId);
		}
    	return true;
	}

    @Override
    public boolean isValidAlias(String channelId, Long templateId, String alias) {
        TemplateInfo templateInfo = new TemplateInfo();
        if(templateId!=null){
            templateInfo.setId(templateId);
        }
        templateInfo.setChannelInfo(channelService.getById(channelId));
        templateInfo.setAlias(alias);
        try {
            Template template = new Template(templateInfo);
        } catch (BaseCheckedException e) {
            if(Template.INVALID_ALIAS.equals(e.getMsgKey())){
                return false;
            }
        }
        return true;
    }

}
